package com.xtaller.easy.admin.controller.unified;

import com.alibaba.fastjson.JSONObject;
import com.xtaller.common.kit.DESKit;
import com.xtaller.common.kit.OSKit;
import com.xtaller.common.kit.TimeKit;
import com.xtaller.easy.admin.base.TApi;
import com.xtaller.easy.admin.config.R;
import com.xtaller.easy.admin.service.impl.DeveloperService;
import com.xtaller.easy.admin.specification.Generator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.List;

/**
 * Created by Taller on 2018/5/11
 */
@Api(tags = "开发者管理api")
@RestController
@RequestMapping("/v1/developer")
@CrossOrigin   //跨域服务注解
public class DeveloperApi extends TApi {
    @Autowired
    private DeveloperService developerService;
    private static final String database = "easy-admin";

    @GetMapping("/generator")
    @ApiOperation(value = "读取数据库结构")
    public Object getTables(){
        return R.ok(getTable());
    }

    @GetMapping("/generator/{tableName}")
    @ApiOperation(value = "读取数据库表结构")
    public Object getTableCols(@PathVariable("tableName") String tableName){
        String sql = String.format("select column_name,data_type,column_type,column_comment from information_schema.columns\n" +
                "where table_name = '%s' AND table_schema='easy-admin'", tableName);
        return R.ok(developerService.runSql(sql));
    }

    @PostMapping("/generator")
    @ApiOperation(value = "后端代码生成")
    public Object autoGenerator(@RequestBody Generator object){
        ResultSet cols = getTableCol(object.getTableName());
        if(cols == null)
            return R.error("表结构尚未构建");
        Boolean ok = generatorCode(cols, object);
        if(ok)
            return R.ok("生成成功");
        return R.error("生成失败");
    }
    private Boolean generatorCode(ResultSet rs, Generator object){
        String tableName = object.getTableName();
        int tableId = object.getCode();
        String time = TimeKit.formatNow("yyyy/MM/dd");
        Boolean linux = OSKit.isLinux();
        /***********************基础路径配置**************************/
        //实体包/路径
        String package_model = "com.xtaller.easy.admin.model";
        // String path_model = "\\model\\";
        String path_model = "/model/";
        //Mapper/路径
        String package_mapper = "com.xtaller.easy.admin.mapper";
        // String path_mapper = "\\mapper\\";
        String path_mapper = "/mapper/";
        //IService
        String package_iservice = "com.xtaller.easy.admin.service";
        // String path_iservice = "\\service\\";
        String path_iservice = "/service/";
        //Service
        String package_service = "com.xtaller.easy.admin.service.impl";
        // String path_service = "\\service\\impl\\";
        String path_service = "/service/impl/";
        //项目路径  linux-->
        String project = "/api/src/main/java/com/xtaller/easy/admin";
        // String project = "\\api\\src\\main\\java\\com\\xtaller\\easy\\admin";
        if(!linux){
            path_model = "\\model\\";
            path_mapper = "\\mapper\\";
            path_iservice = "\\service\\";
            path_service = "\\service\\impl\\";
            project = "\\api\\src\\main\\java\\com\\xtaller\\easy\\admin";
        }
        //项目根目录
        File directory = new File(".");
        try {
            String path = directory.getCanonicalPath();

            //完整项目路径
            path = path + project;
            StringBuffer sb = new StringBuffer();
            StringBuffer sb1 = new StringBuffer();

            JSONObject code = new JSONObject();
            /*************************** Model ***************************/
            sb.append("package " + package_model + ";\n\n");
            sb.append("import com.baomidou.mybatisplus.activerecord.Model;\n");
            sb.append("import com.baomidou.mybatisplus.annotations.TableName;\n");
            sb.append("import com.xtaller.common.kit.IdKit;\n");
            sb.append("import java.io.Serializable;\n\n");
            sb.append("/**\n");
            sb.append("* Created by Taller on "+time+"\n");
            sb.append("*/\n");
            sb.append("@SuppressWarnings(\"serial\")\n");
            sb.append("@TableName(value = \"" + tableName + "\")\n");
            sb.append("public class "+formatName(tableName)+" extends Model<"+formatName(tableName)+"> {\n");
            //定义属性
            while (rs.next()) {
                String id = "";
                if(rs.getString(1).equals("id")){
                    id = " = IdKit.getId("+ tableId +")";
                }
                sb.append("  private "+ formatType(rs.getString(2))+" "+rs.getString(1) + id+";" );
                sb.append("\n");

                sb1.append("  public "+formatType(rs.getString(2))+" get" + formatGS(rs.getString(1)) + "() { \n");
                sb1.append("      return " + rs.getString(1) + ";\n");
                sb1.append("  } \n");
                sb1.append("  public void set" + formatGS(rs.getString(1)) + "("+formatType(rs.getString(2))+" "+rs.getString(1)+") { \n");
                sb1.append("      this." + rs.getString(1) + " = "+rs.getString(1)+";\n");
                sb1.append("  } \n");
            }
            sb.append("\n");
            sb.append(sb1.toString());
            sb.append("  @Override\n");
            sb.append("  protected Serializable pkVal() {\n");
            sb.append("      return id;\n");
            sb.append("  }\n");
            sb.append("}\n");
            writeFile((path+path_model+formatName(tableName)+".java"),sb);
            code.put("model",sb);

            /*************************** Mapper ***************************/
            sb = new StringBuffer();
            sb.append("package " + package_mapper + ";\n\n");
            sb.append("import com.baomidou.mybatisplus.mapper.BaseMapper;\n");
            sb.append("import "+package_model+"." + formatName(tableName) + ";\n\n");
            sb.append("import org.apache.ibatis.annotations.Mapper;");
            sb.append("/**\n");
            sb.append("* Created by Taller on "+time+"\n");
            sb.append("*/\n");
            sb.append("@Mapper \n");
            sb.append("public interface " + formatName(tableName) + "Mapper extends BaseMapper<" + formatName(tableName) + "> {\n");
            sb.append("}");
            writeFile2((path+path_mapper+formatName(tableName)+"Mapper.java"),sb);
            code.put("mapper",sb);

            /*************************** IService *************************/
            sb = new StringBuffer();
            sb.append("package " + package_iservice + ";\n\n");
            sb.append("import java.util.List;\n");
            sb.append("import com.xtaller.common.bean.Where;\n");
            sb.append("import "+package_model+"." + formatName(tableName) + ";\n\n");
            sb.append("/**\n");
            sb.append("* Created by Taller on "+time+"\n");
            sb.append("*/\n");
            sb.append("public interface I" + formatName(tableName) + "Service {\n");

            sb.append("   /******************* CURD ********************/ \n");
            sb.append("   // 创建 \n");
            sb.append("   "+formatName(tableName)+" createModel("+formatName(tableName)+" model); \n");

            sb.append("   // 删除 \n");
            sb.append("   Boolean deleteModel(Object ids,String reviser);\n");

            sb.append("   // 修改 \n");
            sb.append("   "+formatName(tableName)+" updateModel("+formatName(tableName)+" model); \n");

            sb.append("   // 查询 \n");
            sb.append("   List<"+formatName(tableName)+"> findByIds(Object ids);\n");

            sb.append("   // 属于 \n");
            sb.append("   Boolean exist(List<Where> w); \n");

            sb.append("   // 查询一个id是否存在 \n");
            sb.append("   Boolean existId(Object id); \n");

            sb.append("   // 获取所有 \n");
            sb.append("   List<"+formatName(tableName)+"> getData();\n");

            sb.append("   /******************* CURD ********************/ \n \n");
            sb.append("}");
            writeFile2((path+path_iservice+"I"+formatName(tableName)+"Service.java"),sb);
            code.put("iService",sb);

            /*************************** Service **************************/

            sb = new StringBuffer();
            sb.append("package " + package_service + ";\n\n");
            sb.append("import com.xtaller.easy.admin.base.TServiceImpl;\n");
            sb.append("import com.xtaller.easy.admin.mapper." + formatName(tableName) + "Mapper;\n");
            sb.append("import com.xtaller.easy.admin.model." + formatName(tableName) + ";\n");
            sb.append("import com.xtaller.easy.admin.service.I" + formatName(tableName) + "Service;\n");
            sb.append("import org.springframework.stereotype.Service;\n\n");
            sb.append("import java.util.List;\n");
            sb.append("import com.xtaller.common.convert.W;\n");
            sb.append("import com.xtaller.common.bean.Where;\n");
            sb.append("/**\n");
            sb.append("* Created by Taller on "+time+"\n");
            sb.append("*/\n");
            sb.append("@Service\n");
            sb.append("public class " + formatName(tableName) + "Service extends TServiceImpl<" + formatName(tableName) + "Mapper," + formatName(tableName) + "> implements I" + formatName(tableName) + "Service {\n");
            sb.append("   /**************************CURD begin******************************/ \n");

            sb.append("   // 创建\n");
            sb.append("   @Override\n");
            sb.append("   public "+formatName(tableName)+" createModel("+formatName(tableName)+" model) {\n");
            sb.append("       if(this.insert(model))\n");
            sb.append("           return this.selectById(model.getId());\n");
            sb.append("       return null;\n");
            sb.append("   }\n \n");

            sb.append("   // 删除\n");
            sb.append("   @Override\n");
            sb.append("   public Boolean deleteModel(Object ids,String reviser) {\n");
            sb.append("       return this.delete(ids,reviser);\n");
            sb.append("   }\n \n");

            sb.append("   // 修改\n");
            sb.append("   @Override\n");
            sb.append("   public "+formatName(tableName)+" updateModel("+formatName(tableName)+" model) {\n");
            sb.append("       if(this.update(model))\n");
            sb.append("           return this.selectById(model.getId());\n");
            sb.append("       return null;\n");
            sb.append("   }\n \n");

            sb.append("   // 查询\n");
            sb.append("   @Override\n");
            sb.append("   public List<"+formatName(tableName)+"> findByIds(Object ids) {\n");
            sb.append("       return this.selectByIds(ids);\n");
            sb.append("   }\n \n");

            sb.append("   // 属于\n");
            sb.append("   @Override\n");
            sb.append("   public Boolean exist(List<Where> w) {\n");
            sb.append("       w.add(new Where(\"1\"));\n");
            sb.append("       return this.query(w).size() > 0;\n");
            sb.append("   }\n \n");

            sb.append("   // 查询一个id是否存在\n");
            sb.append("   @Override\n");
            sb.append("   public Boolean existId(Object id) {\n");
            sb.append("       where = W.f(\n");
            sb.append("               W.and(\"id\",\"eq\",id),\n");
            sb.append("               W.field(\"1\")\n");
            sb.append("       );\n");
            sb.append("       return this.query(where).size() > 0;\n");
            sb.append("   }\n \n");

            sb.append("   // 获取所有\n");
            sb.append("   @Override\n");
            sb.append("   public List<"+formatName(tableName)+"> getData() {\n");
            sb.append("       where = W.f(\n");
            sb.append("               W.and(1,\"eq\",1)\n");
            sb.append("       );\n");
            sb.append("       return this.query(where);\n");
            sb.append("   }\n \n");

            sb.append("   /**************************CURD end********************************/ \n");
            sb.append("\n");

            sb.append("}");
            writeFile2((path+path_service+formatName(tableName)+"Service.java"),sb);
            code.put("service",sb);
            return true;
        }catch (Exception ex){
            return false;
        }

    }

    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    private ResultSet getTableCol(String tableName){
        ResultSet rs;
        try {
            Connection conn = null;
            conn = DriverManager.getConnection(url, DESKit.decrypt(username), DESKit.decrypt(password));
            PreparedStatement pstm = conn.prepareStatement("select COLUMN_name,data_type from information_schema.columns where table_name = '"+tableName+"' AND table_schema='"+database+"' ");
            rs = pstm.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
            rs = null;
        }
        return rs;
    }
    // 写文件
    private void writeFile(String path, StringBuffer sb) throws IOException {
        File file = new File(path);
        FileWriter fw = null;
        BufferedWriter writer = null;
        if(file.exists()){
            file.delete();
        }
        file.createNewFile();
        fw = new FileWriter(file);
        writer = new BufferedWriter(fw);
        writer.write(sb.toString());

        writer.flush();
        writer.close();
        fw.close();
    }
    private void writeFile2(String path, StringBuffer sb) throws IOException {
        File file = new File(path);
        FileWriter fw = null;
        BufferedWriter writer = null;
        if(!file.exists()){
            file.createNewFile();
            fw = new FileWriter(file);
            writer = new BufferedWriter(fw);
            writer.write(sb.toString());
            writer.flush();
            writer.close();
            fw.close();
        }
    }
    private String formatType(String db){
        String type = "String";
        if(db.equals("bigint")){
            type = "String";
        }
        if(db.equals("tinyint")){
            type = "Integer";
        }
        if(db.equals("smallint")){
            type = "Integer";
        }
        if(db.equals("int")){
            type = "Integer";
        }

        return type;
    }
    private String formatName(String name){
        String[] item = name.split("_");
        int len = item.length;
        String fileName = "";
        for(int i=0;i<len;i++){
            fileName += item[i].substring(0, 1).toUpperCase() + item[i].substring(1);
        }
        return fileName;
    }
    private String formatGS(String field){
        return field.substring(0, 1).toUpperCase()+ field.substring(1,field.length());
    }
    // 读取数据库结构
    private List<JSONObject> getTable(){
        String sql = String.format("select table_name,ifnull(engine,'') engine,ifnull(table_rows,0) table_rows,IFNULL(create_time,'') create_time,IFNULL(update_time,'') update_time,ifnull(table_collation,'') table_collation,table_comment,(case table_type when 'view' then 888 else RIGHT(trim(table_comment),3) end ) `code` from information_schema.tables where table_schema='%s' and (table_type='base table' or table_type='view') order by table_name ",
                database);
        return developerService.runSql(sql);
    }


}
